import mysql.connector as mysql
from config import host, user, password
import pandas as pd
import numpy as np
import plotly.graph_objs as go
import plotly.offline as pyo
import plotly.express as px
from plotly.subplots import make_subplots
import math
pd.options.mode.chained_assignment = None
con = mysql.connect(user=user,password=password,host=host,database='team3')
cursor = con.cursor()
query1 = "SELECT * FROM opponents"
cursor.execute(query1)
results = cursor.fetchall()
matches = pd.DataFrame(results,columns=['team_name','date','opponent_name'])
indexes = []
for index, row in matches.iterrows():
if index == len(matches) -1:
break
if row['team_name'] == matches.loc[index+1,'opponent_name']:
indexes.append(index)
matches.drop(indexes,inplace=True)
matches['month'] = pd.DatetimeIndex(matches['date']).month
matches['year'] = pd.DatetimeIndex(matches['date']).year
group_matches = matches.groupby(by=['year','month']).count()['team_name']
match_freq = pd.DataFrame(list(group_matches.index), columns=['year','month'])
match_freq['day'] = 1
match_freq['date'] = pd.to_datetime(match_freq)
match_freq = match_freq[['date']]
match_freq['freq'] = group_matches.values
date_range = list(pd.date_range('2019-06-01','2023-05-30',freq='MS'))
for date in date_range:
if date not in list(match_freq['date']):
row = {'date':date,'freq':0}
match_freq = match_freq.append(row,ignore_index=True)
match_freq.sort_values(by=['date'],inplace=True)
match_freq.reset_index(inplace=True)
fig = px.line(match_freq, x="date", y="freq", title='Liczba spotkań każdego miesiąca')
fig.update_layout(xaxis_title='czas',
yaxis_title='liczba meczy',
title_x=0.5)
fig.show()
Na powyższym wykresie widać, że przez pierwsze pół roku działalności klubu nasze drużyny nie rozgrywały żadnych meczy. Pierwsze spotkania odbyły się dopiero na początku roku 2020. Niestety rozwój naszego klubu zatrzymał lockdown spowodowany pandemią covid 19 i od początku marca do końca czerwca roku 2020 również nie rozgrywaliśmy meczy.
W lipcu 2020 roku obserwujemy nagły wzrost ilości meczy, a później już powolny rozwój klubu. Liczba spotkań przejawia tendencję rosnącą, przy czym najwięcej meczy (ponad 50) rozegranych zostało niedawno, bo w maju 2022 roku.
Na wykresie przedstawiona została także liczba meczy zaplanowanych na każdy miesiąc przyszłego sezonu.
query2 = '''SELECT team_name, team_score, opponent_score, team_score > opponent_score, team_score < opponent_score
FROM matches WHERE team_score IS NOT NULL'''
cursor.execute(query2)
results = cursor.fetchall()
scores = pd.DataFrame(results,columns=['team_name','team_score','opponent_score','match_won','match_lost'])
scores = scores.groupby(by=['team_name']).sum()[['match_won','match_lost']]
scores.sort_values(by=['team_name'],inplace=True)
lost = scores['match_lost']
won = scores['match_won']
teams = list(scores.index)
layout = go.Layout(yaxis=go.layout.YAxis(
ticktext=teams,
range=[0, len(teams)],
title='Teams'),
xaxis=go.layout.XAxis(
range=[-lost.max()-1, won.max()+1],
tickvals=[i for i in range(-30,40,10)],
ticktext=[str(abs(i)) for i in range(-30,40,10)],
title='Number'),
barmode='overlay',
autosize=False,
width=800,
height=1100,
title='Bilans wygranych i przegranych meczy',
title_x=0.5,
bargap=0.1)
data = [go.Bar(y=teams,
x=won,
orientation='h',
name='wygrane',
text=won,
hoverinfo='x+y',
marker=dict(color='#636efa'),
textangle=0,
#textposition="outside"
),
go.Bar(y=teams,
x=-lost,
orientation='h',
name='przegrane',
text=lost,
hoverinfo='text+y',
marker=dict(color='#ef553b'),
textangle=0,
#textposition="outside"
)]
#fig.update_traces(textangle=0, textposition="outside")
pyo.iplot(dict(data=data, layout=layout))
Powyższy wykres piramidowy przedstawia liczbę wygranych i przegranych meczy dla każdej z naszych drużyn. Widać duże rozbieżności pomiędzy drużynami.
Sześć drużyn ('Baby Broomers', 'Curlers Terriers', 'Calgary Metros', 'Montreal Vipers', 'Rolling Stones' i 'Super Atlantics') rozegrało nie więcej niż sześć meczy, co może wynikać z braku możliwości skopletowania składu. Natomiast osiem drużyn odbyło ponad 30 spotkań.
Istenieją też znaczne różnice pomiędzy bilansem wygranych i przegranych meczy. Do najlepszych drużyn zdecydowanie możemy zaliczyć 'Vancouver Fury', którzy wygrali 82% z rozegranych meczy oraz 'Montreal Bruins' którzy mają najwięcej wygranych meczy ze wszystkich drużyn i niewielką ilość przegranych. Wysoko plasują się także 'Calgary Rockets', którzy na 20 rozgranych meczy nie przegrali ani jednego. Do innych drużyn, które wygrały wszystkie swoje mecze możemy także zaliczyć 'Toronto Olympics', 'Montreal Braves', 'Curlers Terriers' oraz 'Calgary Metros'. Musimy jednak wziąć pod uwagę, że dwie ostatnie drużyny rozegrały mniej meczy w porównaniu do innych drużyn o idealnej skuteczności.
Najgorszymi drużynami okazały się 'Vancouver Islanders' - przegrali wszytskie 32 mecze! Dużą przewagę przegranych do wygranych meczy mają także 'Toronto Eagels', 'Stone Mariners' oraz 'Ice Sabres'.
query3 = "SELECT birthdate, join_date, retire_date, age_category FROM personal_info INNER JOIN teams USING(team_name)"
cursor.execute(query3)
results = cursor.fetchall()
dates = pd.DataFrame(results,columns=['birthdate','join_date','retire_date','age_category'])
junior_age = pd.DataFrame(columns=['date','mean_age'])
adult_age = pd.DataFrame(columns=['date','mean_age'])
date_range2 = list(pd.date_range('2019-06-01','2022-05-30',freq='W'))
for date in date_range2:
j_ages = []
a_ages = []
for index, row in dates.iterrows():
age = math.floor((date - pd.to_datetime(row['birthdate']))/np.timedelta64(1, 'Y'))
if (row['join_date'] <= date) and ((row['retire_date'] == None) or (row['retire_date'] >= date)):
if row['age_category'] == 'junior':
j_ages.append(age)
elif row['age_category'] == 'adult':
a_ages.append(age)
if j_ages != []:
row = {'date':date,'mean_age':np.mean(j_ages)}
junior_age = junior_age.append(row,ignore_index=True)
if a_ages != []:
row = {'date':date,'mean_age':np.mean(a_ages)}
adult_age = adult_age.append(row,ignore_index=True)
fig = px.line(junior_age, x="date", y="mean_age", title='Średni wiek juniorów')
fig.update_layout(xaxis_title='czas',
yaxis_title='średin wiek',
title_x=0.5)
fig.show()
fig = px.line(adult_age, x="date", y="mean_age", title='Średni wiek dorosłych graczy')
fig.update_layout(xaxis_title='czas',
yaxis_title='średni wiek',
title_x=0.5)
fig.show()
Dwa powyższe wykresy przedstawiają średni wiek w zależności od czasu dla graczy z kategorii juniorów i dorosłych.
W obu przypadkach zauważalna jest ogólna tendencja wzrostowa, co jest logiczne biorąc pod uwagę, że nasi gracze z roku na rok są coraz starsi. Widać jednak, że miejscami średni wiek znacząco spada, zwłaszcza na początku naszej działalności, co jest spowodowane odchodzeniem graczy z klubu. Spadki są bardzo widoczne również ze względu na niewielką ilość graczy na początku istnienia klubu.
Dla dorosłych obserwujemy jednak dwa większe spadki tekże w późniejszych miesiącach - w połowie roku 2020 i na początku 2022.
Możemy również zauważyć, że średni wiek juniorów nie przekracza 14 lat, a pierwsi gracze, który dołączyli mieli śrdednio 9 lat. Dla dorosłych natomiast średni wiek nie przekracza 40 lat, a pierwsi gracze mieli średnio 28 lat.
query4 = '''SELECT gender, join_date, retire_date
FROM personal_info
INNER JOIN people USING(person_id)
INNER JOIN gender USING(first_name)
WHERE team_name IS NOT NULL'''
cursor.execute(query4)
results = cursor.fetchall()
players = pd.DataFrame(results,columns=['gender','join_date','retire_date'])
women_number = pd.DataFrame(columns=['date','number','gender'])
men_number = pd.DataFrame(columns=['date','number','gender'])
for date in date_range2:
women_counter = 0
men_counter = 0
for index, row in players.iterrows():
if (row['join_date'] <= date) and ((row['retire_date'] == None) or (row['retire_date'] >= date)):
if row['gender'] == 'F':
women_counter += 1
elif row['gender'] == 'M':
men_counter += 1
row_w = {'date':date,'number':women_counter,'gender':'female'}
row_m = {'date':date,'number':men_counter,'gender':'male'}
women_number = women_number.append(row_w,ignore_index=True)
men_number = men_number.append(row_m,ignore_index=True)
fig = px.line(pd.concat([women_number,men_number]), x="date", y="number", color='gender',title='Ilość graczy w zależności od czasu')
fig.update_layout(xaxis_title='czas',
yaxis_title='ilość graczy',
title_x=0.5)
fig.show()
Na powyższym wykresie obserwujemy tendencję wzrostową ilości graczy w klubie, zarówno dla kobiet i dla mężczyzn, przy czym liczba kobiet nigdy nie przekracza ilości mężczyzn. Oznacza to, że nasz klub się powiększa, a to wyjaśnia wcześniej zaobserwowany wzrost w ilości meczów.
Na podstawie graczy którzy brali udział w meczu na jakiejś pozycji (jeśli mają przypisaną pozycję, to grali a nie siedzieli), szukamy tych którzy mają największą skuteczność (ilość wygranych do wszystkich meczy). Szukamy wśród dorosłych i juniorów oddzielnie, zaczynając od dorosłych.
def display_best_players(data, number):
data['success_rate'] = data['won']/data['played']
data['success_rate'] = round(data['success_rate'].astype(float), 5)
data = data[['first_name','last_name','won', 'played', 'success_rate']]
data = data.sort_values(by=['success_rate', 'played'], ascending=False)
data.reset_index(drop=True, inplace=True)
data.index = data.index + 1
return data[:number]
def display_player_info(data):
today = pd.to_datetime('2022-05-30')
for index, row in data.iterrows():
age = math.floor((today - pd.to_datetime(row['birthdate']))/np.timedelta64(1, 'Y'))
if row['gender'] == 'M':
gender = 'mężczyzna'
else:
gender = 'kobieta'
print('{}) {} {}, {} w wieku {} lat, z drużyny {}'.format(index+1, row['first_name'], row['last_name'], gender, age, row['team_name']))
query_best_adults = '''
SELECT SUM(team_score > opponent_score) AS won, COUNT(team_score > opponent_score) AS played, first_name, last_name
FROM positions
LEFT JOIN people USING (person_id)
LEFT JOIN personal_info USING (person_id)
LEFT JOIN matches USING (team_name, date)
LEFT JOIN teams USING (team_name)
WHERE team_score IS NOT NULL AND age_category = 'adult'
GROUP BY person_id
'''
cursor.execute(query_best_adults)
result_adults = cursor.fetchall()
data_adults = pd.DataFrame(result_adults,columns=['won', 'played','first_name','last_name'])
display_best_players(data_adults, 40)
| first_name | last_name | won | played | success_rate | |
|---|---|---|---|---|---|
| 1 | Zacharia | Donaldson | 15 | 15 | 1.00000 |
| 2 | Abdurrahman | Huynh | 13 | 13 | 1.00000 |
| 3 | Alexandro | Guerin | 11 | 11 | 1.00000 |
| 4 | Dorian | Lam | 11 | 11 | 1.00000 |
| 5 | Nick | Small | 10 | 10 | 1.00000 |
| 6 | Manley | Gravel | 9 | 9 | 1.00000 |
| 7 | Eduardo | Costa | 7 | 7 | 1.00000 |
| 8 | Gena | Vezina | 5 | 5 | 1.00000 |
| 9 | Glen | Christie | 5 | 5 | 1.00000 |
| 10 | Reno | Duchesne | 4 | 4 | 1.00000 |
| 11 | Sylvain | Preston | 4 | 4 | 1.00000 |
| 12 | Melville | Warren | 3 | 3 | 1.00000 |
| 13 | Israel | Snow | 2 | 2 | 1.00000 |
| 14 | Kwabena | Arseneault | 2 | 2 | 1.00000 |
| 15 | Kaida | Joly | 1 | 1 | 1.00000 |
| 16 | Aliah | Hawkins | 1 | 1 | 1.00000 |
| 17 | Carlos | Lalonde | 1 | 1 | 1.00000 |
| 18 | Neal | Chow | 1 | 1 | 1.00000 |
| 19 | Nasir | Burke | 1 | 1 | 1.00000 |
| 20 | Marlyne | Lloyd | 1 | 1 | 1.00000 |
| 21 | Gerardo | McCallum | 1 | 1 | 1.00000 |
| 22 | Ezio | Labrecque | 1 | 1 | 1.00000 |
| 23 | Alayah | Long | 1 | 1 | 1.00000 |
| 24 | Akhil | Berube | 13 | 14 | 0.92857 |
| 25 | Sathana | Lo | 9 | 10 | 0.90000 |
| 26 | Emile | Burton | 30 | 34 | 0.88235 |
| 27 | Juliano | Lord | 15 | 17 | 0.88235 |
| 28 | Ankit | Cousineau | 15 | 17 | 0.88235 |
| 29 | Jean-philippe | Mercer | 7 | 8 | 0.87500 |
| 30 | Patricia-anne | Audet | 7 | 8 | 0.87500 |
| 31 | Thierry | Donnelly | 25 | 29 | 0.86207 |
| 32 | Gordon | Klassen | 18 | 21 | 0.85714 |
| 33 | Bohdan | George | 6 | 7 | 0.85714 |
| 34 | Daryn | Labelle | 17 | 20 | 0.85000 |
| 35 | Dhyan | Fillion | 16 | 19 | 0.84211 |
| 36 | Maksim | Berry | 20 | 24 | 0.83333 |
| 37 | Johan | Webb | 15 | 18 | 0.83333 |
| 38 | Stavros | Thiessen | 14 | 17 | 0.82353 |
| 39 | Yanick | Dhaliwal | 23 | 28 | 0.82143 |
| 40 | Jake | Morris | 9 | 11 | 0.81818 |
query_adult_info = '''
SELECT first_name, last_name, gender, birthdate, team_name
FROM people
LEFT JOIN personal_info USING (person_id)
LEFT JOIN gender USING (first_name)
WHERE (first_name = 'Zacharia' AND last_name = 'Donaldson') OR
(first_name = 'Abdurrahman' AND last_name = 'Huynh') OR
(first_name = 'Alexandro' AND last_name = 'Guerin') OR
(first_name = 'Dorian' AND last_name = 'Lam') OR
(first_name = 'Nick' AND last_name = 'Small')
GROUP BY person_id
'''
cursor.execute(query_adult_info)
info_adults = cursor.fetchall()
info_adults = pd.DataFrame(info_adults,columns=['first_name', 'last_name', 'gender', 'birthdate', 'team_name'])
Dość spodziewane było pojawienie się w czołówce graczy którzy grali niewiele meczy i udało im się je wygrać, dlatego wyświetlona jest również liczba meczy oraz sortowanie po niej by móc stwierdzić, dla których zwycięstwa nie są przypadkiem. W powyższej tabeli widzimy kilku świetnych graczy z $100\%$ skutecznością, a grali oni w ponad jednym meczu! Najlepsza 5 z dorosłych graczy w CurlingMasters to:
display_player_info(info_adults)
1) Alexandro Guerin, mężczyzna w wieku 29 lat, z drużyny Calgary Rockets 2) Zacharia Donaldson, mężczyzna w wieku 42 lat, z drużyny Calgary Rockets 3) Abdurrahman Huynh, mężczyzna w wieku 45 lat, z drużyny Calgary Rockets 4) Nick Small, mężczyzna w wieku 49 lat, z drużyny Calgary Rockets 5) Dorian Lam, mężczyzna w wieku 36 lat, z drużyny Calgary Rockets
Okazuje się, że panowie pochodzą z jednej drużyny, jest to zatem mistrzowska drużyna! Warto również zwrócić uwagę na takich zawodników jak: Akhil Berube, Sathana Lo, Emile Burton, Juliano Lord, Ankit Cousineau, których wyniki są również obiecujące, ze względu na ilość rozegranych przez nich meczy.
query_best_juniors = '''
SELECT SUM(team_score > opponent_score) AS won, COUNT(team_score > opponent_score) AS played, first_name, last_name
FROM positions
LEFT JOIN people USING (person_id)
LEFT JOIN personal_info USING (person_id)
LEFT JOIN matches USING (team_name, date)
LEFT JOIN teams USING (team_name)
WHERE team_score IS NOT NULL AND age_category = 'junior'
GROUP BY person_id
'''
cursor.execute(query_best_juniors)
result_junior = cursor.fetchall()
data_juniors = pd.DataFrame(result_junior,columns=['won', 'played','first_name','last_name'])
display_best_players(data_juniors, 40)
| first_name | last_name | won | played | success_rate | |
|---|---|---|---|---|---|
| 1 | Israel | Chevalier | 13 | 13 | 1.0 |
| 2 | Daylen | Larsen | 13 | 13 | 1.0 |
| 3 | Craig | McCarthy | 13 | 13 | 1.0 |
| 4 | Carl | Perron | 13 | 13 | 1.0 |
| 5 | Jahaan | Turgeon | 9 | 9 | 1.0 |
| 6 | Mackayla | Little | 8 | 8 | 1.0 |
| 7 | Petra | Reimer | 8 | 8 | 1.0 |
| 8 | Rania | Faucher | 6 | 6 | 1.0 |
| 9 | Fisher | Aubin | 6 | 6 | 1.0 |
| 10 | Ioanna | Brar | 6 | 6 | 1.0 |
| 11 | Lucille | Marsh | 5 | 5 | 1.0 |
| 12 | Leita | Lam | 5 | 5 | 1.0 |
| 13 | Karys | Carter | 5 | 5 | 1.0 |
| 14 | Hendrick | Chow | 5 | 5 | 1.0 |
| 15 | Jenson | Yu | 5 | 5 | 1.0 |
| 16 | Chastity | Tessier | 5 | 5 | 1.0 |
| 17 | Patsy | Lucas | 4 | 4 | 1.0 |
| 18 | Jameson | Chin | 4 | 4 | 1.0 |
| 19 | Ishani | Cole | 4 | 4 | 1.0 |
| 20 | Piranavan | Ferreira | 3 | 3 | 1.0 |
| 21 | Lucian | Demers | 3 | 3 | 1.0 |
| 22 | Roslyn | Sidhu | 3 | 3 | 1.0 |
| 23 | Jeannedarc | Kim | 3 | 3 | 1.0 |
| 24 | Kace | Wiebe | 2 | 2 | 1.0 |
| 25 | Calen | Buchanan | 2 | 2 | 1.0 |
| 26 | Brandon-lee | Fong | 2 | 2 | 1.0 |
| 27 | Ashlynn | Paradis | 2 | 2 | 1.0 |
| 28 | Jameel | Faucher | 2 | 2 | 1.0 |
| 29 | Tesla | Tan | 2 | 2 | 1.0 |
| 30 | Avrom | Law | 2 | 2 | 1.0 |
| 31 | Muad | Saunders | 2 | 2 | 1.0 |
| 32 | Betty | OConnor | 1 | 1 | 1.0 |
| 33 | Arush | Chartrand | 1 | 1 | 1.0 |
| 34 | Inayah | Beaudin | 1 | 1 | 1.0 |
| 35 | Mallory | Marcotte | 1 | 1 | 1.0 |
| 36 | Marie-paule | Doiron | 1 | 1 | 1.0 |
| 37 | Maddex | Reed | 1 | 1 | 1.0 |
| 38 | Kiyan | Lord | 1 | 1 | 1.0 |
| 39 | Moosa | Erickson | 1 | 1 | 1.0 |
| 40 | Mackayla | Menard | 1 | 1 | 1.0 |
query_junior_info = '''
SELECT first_name, last_name, gender, birthdate, team_name
FROM people
LEFT JOIN personal_info USING (person_id)
LEFT JOIN gender USING (first_name)
WHERE (first_name = 'Israel' AND last_name = 'Chevalier') OR
(first_name = 'Daylen' AND last_name = 'Larsen') OR
(first_name = 'Craig' AND last_name = 'McCarthy') OR
(first_name = 'Carl' AND last_name = 'Perron') OR
(first_name = 'Jahaan' AND last_name = 'Turgeon')
GROUP BY person_id
'''
cursor.execute(query_junior_info)
info_juniors = cursor.fetchall()
info_juniors = pd.DataFrame(info_juniors,columns=['first_name', 'last_name', 'gender', 'birthdate', 'team_name'])
Juniorów z idealną skutecznością mamy jeszcze więcej niż dorosłych. Przyrzyjmy się dokładniej top 5:
display_player_info(info_juniors)
1) Israel Chevalier, mężczyzna w wieku 20 lat, z drużyny Montreal Braves 2) Daylen Larsen, mężczyzna w wieku 17 lat, z drużyny Montreal Braves 3) Craig McCarthy, mężczyzna w wieku 10 lat, z drużyny Montreal Braves 4) Carl Perron, mężczyzna w wieku 10 lat, z drużyny Montreal Braves 5) Jahaan Turgeon, mężczyzna w wieku 9 lat, z drużyny Toronto Olympics
Widzimy, że najlepsi zawodnicy, są to mężczyźni, znów w większości z jednej drużyny. Jest to najprawdopdobniej spowodowane przez przypisywanie skuteczności (wykorzystywanej do generacji wyników meczu) do drużyny. Dlatego jeśli drużyna ma wysoką skuteczność, oraz rozegrała sporo meczy, to właśnie jej członkowie pojawią się wysoko i obok siebie w rankingu. Warto zwrócić uwagę na wielki potencjał Jahaan Turgeon, który już w wieku $9$ lat pojawił się w top $5$.
Chcemy wybrać najlepszych zawodników do mistrzowskich drużyn, które będzie reprezentować cały nasz klub. Nie zwracamy uwagi na miasta, czy drużyny graczy bo chcemy dobrać najlepszą możliwą osobę na dane stanowisko w drużynie. Graczy będziemy wybierać do drużyny męskiej lub żeńskiej w zależności od kategori wiekowej.
def best_for_position(data, position):
data = data[data['position'] == position]
data['success_rate'] = data['won']/data['played']
data['success_rate'] = round(data['success_rate'].astype(float), 5)
today = pd.to_datetime('2022-05-30')
age = []
for index, row in data.iterrows():
age.append(math.floor((today - pd.to_datetime(row['birthdate']))/np.timedelta64(1, 'Y')))
data['age'] = age
data = data[['first_name', 'last_name', 'position','played', 'success_rate', 'gender', 'age', 'team_name']]
data = data.sort_values(by=['success_rate', 'played'], ascending=False)
data.reset_index(drop=True, inplace=True)
data.index = data.index + 1
return data[:5]
query_adult_m = '''
SELECT first_name, last_name, positions.position, SUM(team_score > opponent_score), COUNT(team_score > opponent_score), gender, birthdate, team_name
FROM positions
LEFT JOIN people USING (person_id)
LEFT JOIN gender USING (first_name)
LEFT JOIN personal_info USING (person_id)
LEFT JOIN matches USING (team_name, date)
LEFT JOIN teams USING (team_name)
WHERE (team_score IS NOT NULL) AND (age_category = 'adult') AND (gender = 'M')
GROUP BY person_id, positions.position
'''
cursor.execute(query_adult_m)
team_adult_m = cursor.fetchall()
team_adult_m = pd.DataFrame(team_adult_m, columns=['first_name', 'last_name', 'position', 'won', 'played', 'gender', 'birthdate', 'team_name'])
best_for_position(team_adult_m, 'lead')
| first_name | last_name | position | played | success_rate | gender | age | team_name | |
|---|---|---|---|---|---|---|---|---|
| 1 | Emile | Burton | lead | 9 | 1.0 | M | 42 | Montreal Bruins |
| 2 | Zacharia | Donaldson | lead | 7 | 1.0 | M | 42 | Calgary Rockets |
| 3 | Ankit | Cousineau | lead | 7 | 1.0 | M | 37 | Montreal Bruins |
| 4 | Alexandro | Guerin | lead | 5 | 1.0 | M | 29 | Calgary Rockets |
| 5 | Juliano | Lord | lead | 5 | 1.0 | M | 32 | Vancouver Fury |
best_for_position(team_adult_m, 'vice')
| first_name | last_name | position | played | success_rate | gender | age | team_name | |
|---|---|---|---|---|---|---|---|---|
| 1 | Stavros | Thiessen | vice | 6 | 1.0 | M | 38 | Cold Colts |
| 2 | Marcelo | Dion | vice | 6 | 1.0 | M | 25 | Vancouver Fury |
| 3 | Gordon | Klassen | vice | 6 | 1.0 | M | 27 | Montreal Bruins |
| 4 | Johan | Webb | vice | 5 | 1.0 | M | 28 | Calgary Bruins |
| 5 | Nick | Small | vice | 5 | 1.0 | M | 49 | Calgary Rockets |
best_for_position(team_adult_m, 'second')
| first_name | last_name | position | played | success_rate | gender | age | team_name | |
|---|---|---|---|---|---|---|---|---|
| 1 | Thierry | Donnelly | second | 11 | 1.0 | M | 39 | Montreal Bruins |
| 2 | Daryn | Labelle | second | 7 | 1.0 | M | 37 | Vancouver Fury |
| 3 | Yanick | Dhaliwal | second | 6 | 1.0 | M | 37 | Montreal Bruins |
| 4 | Abdurrahman | Huynh | second | 4 | 1.0 | M | 45 | Calgary Rockets |
| 5 | Jake | Morris | second | 4 | 1.0 | M | 46 | Cold Huskies |
best_for_position(team_adult_m,'skip')
| first_name | last_name | position | played | success_rate | gender | age | team_name | |
|---|---|---|---|---|---|---|---|---|
| 1 | Gordon | Klassen | skip | 7 | 1.0 | M | 27 | Montreal Bruins |
| 2 | Edsel | Green | skip | 5 | 1.0 | M | 47 | Cold Colts |
| 3 | Dhyan | Fillion | skip | 5 | 1.0 | M | 27 | Vancouver Fury |
| 4 | Zacharia | Donaldson | skip | 4 | 1.0 | M | 42 | Calgary Rockets |
| 5 | Manley | Gravel | skip | 4 | 1.0 | M | 40 | Calgary Rockets |
Widzimy, że wśród drużyn dorosłych mężczyzn najlepsi zawodnicy są z drużyn: Montreal Bruins, Calgary Rockets, Vancouver Fury oraz Cold Colts. Niektórzy zawodnicy osiągają bardzo dobre wyniki na więcej niż jednej pozycji np. Gordon Klassen czy Zacharia Donaldson.
W przypadku tej kategori, najlepszy skład moglibyśmy wybrać z następujących osób:
Widzimy, że wszyscy zawodnicy poza 'vice' są jednoznacznie najlepsi oraz pochodzą z drużyny Montreal Bruins. Na pozycję 'vice', nie możemy wybrać Gordon Klassen, ponieważ jest on już na pozycji 'skip', więc do wyboru mamy dowolnego z pozostałych dwóch graczy. Starvros Thiessen pojawia się jako $38$ najlepszy gracz bez względu na pozycję, przy czym Marcelo Dion nie widać w top $40$, zatem decydujemy się na Starvros Thiessen.
Ostatecznie jako reprezentację dorosłych mężczyzn wybieramy:
query_adult_w = '''
SELECT first_name, last_name, positions.position, SUM(team_score > opponent_score), COUNT(team_score > opponent_score), gender, birthdate, team_name
FROM positions
LEFT JOIN people USING (person_id)
LEFT JOIN gender USING (first_name)
LEFT JOIN personal_info USING (person_id)
LEFT JOIN matches USING (team_name, date)
LEFT JOIN teams USING (team_name)
WHERE (team_score IS NOT NULL) AND (age_category = 'adult') AND (gender = 'F')
GROUP BY person_id, positions.position
'''
cursor.execute(query_adult_w)
team_adult_w = cursor.fetchall()
team_adult_w = pd.DataFrame(team_adult_w, columns=['first_name', 'last_name', 'position', 'won', 'played', 'gender', 'birthdate', 'team_name'])
best_for_position(team_adult_w, 'lead')
| first_name | last_name | position | played | success_rate | gender | age | team_name | |
|---|---|---|---|---|---|---|---|---|
| 1 | Najma | Charlebois | lead | 7 | 1.0 | F | 34 | Game of Stones |
| 2 | Adãle | Meyer | lead | 5 | 1.0 | F | 35 | Game of Stones |
| 3 | Sathana | Lo | lead | 3 | 1.0 | F | 27 | Cold Huskies |
| 4 | Anahita | Roy | lead | 3 | 1.0 | F | 36 | Toronto Penguins |
| 5 | Humaira | Sharpe | lead | 1 | 1.0 | F | 40 | Ice Cougars |
best_for_position(team_adult_w, 'vice')
| first_name | last_name | position | played | success_rate | gender | age | team_name | |
|---|---|---|---|---|---|---|---|---|
| 1 | Sara | Willis | vice | 6 | 1.0 | F | 29 | Game of Stones |
| 2 | Kristie | Bartlett | vice | 4 | 1.0 | F | 49 | Calgary Bruins |
| 3 | Patricia-anne | Audet | vice | 3 | 1.0 | F | 22 | Game of Stones |
| 4 | Laiba | Baird | vice | 2 | 1.0 | F | 48 | Cold Huskies |
| 5 | Gena | Vezina | vice | 1 | 1.0 | F | 31 | Cold Huskies |
best_for_position(team_adult_w, 'second')
| first_name | last_name | position | played | success_rate | gender | age | team_name | |
|---|---|---|---|---|---|---|---|---|
| 1 | Preet | Doiron | second | 3 | 1.0 | F | 39 | Game of Stones |
| 2 | Laiba | Baird | second | 2 | 1.0 | F | 48 | Cold Huskies |
| 3 | Gena | Vezina | second | 2 | 1.0 | F | 31 | Cold Huskies |
| 4 | Domenica | Shah | second | 2 | 1.0 | F | 47 | Calgary Bruins |
| 5 | Aliah | Hawkins | second | 1 | 1.0 | F | 26 | Ice Cougars |
best_for_position(team_adult_w, 'skip')
| first_name | last_name | position | played | success_rate | gender | age | team_name | |
|---|---|---|---|---|---|---|---|---|
| 1 | Adãle | Meyer | skip | 5 | 1.0 | F | 35 | Game of Stones |
| 2 | Anayat | Major | skip | 5 | 1.0 | F | 26 | Toronto Penguins |
| 3 | Sathana | Lo | skip | 3 | 1.0 | F | 27 | Cold Huskies |
| 4 | Kelsie | Gallant | skip | 2 | 1.0 | F | 35 | Toronto Penguins |
| 5 | Patricia-anne | Audet | skip | 2 | 1.0 | F | 22 | Game of Stones |
Dla dorosłych kobiet najlepsze zawodniczki podobnie jak u mężczyzn, pochodzą z powtarzających się drużyn, takich jak: Game of Stones, Cold Huskies, Toronto Penguins, Ice Cougars i Calgary Bruins. Również widzimy zawodniczki świetne bez wzgędu na jakiej pozycji grały np. Adãle Meyer i Sathana Lo.
Bazując na powyższych, najlepszy skład moglibyśmy wybrać z następujących osób:
Wybrane zawodniczki poza 'skip' są z drużyny Game of Stones. Sugerując się drużyną, warto byłoby wybrać Adãle Meyer na tę pozycję, ponieważ najprawdopodobniej zawodniczki które są z jednego teamu, będą w stanie najlepiej razem współpracować.
Zatem jako reprezentację dorosłych kobiet wybieramy drużynę Game of Stones w składzie:
query_junior_m = '''
SELECT first_name, last_name, positions.position, SUM(team_score > opponent_score), COUNT(team_score > opponent_score), gender, birthdate, team_name
FROM positions
LEFT JOIN people USING (person_id)
LEFT JOIN gender USING (first_name)
LEFT JOIN personal_info USING (person_id)
LEFT JOIN matches USING (team_name, date)
LEFT JOIN teams USING (team_name)
WHERE (team_score IS NOT NULL) AND (age_category = 'junior') AND (gender = 'M')
GROUP BY person_id, positions.position
'''
cursor.execute(query_junior_m)
team_junior_m = cursor.fetchall()
team_junior_m = pd.DataFrame(team_junior_m, columns=['first_name', 'last_name', 'position', 'won', 'played', 'gender', 'birthdate', 'team_name'])
best_for_position(team_junior_m, 'lead')
| first_name | last_name | position | played | success_rate | gender | age | team_name | |
|---|---|---|---|---|---|---|---|---|
| 1 | Israel | Chevalier | lead | 5 | 1.0 | M | 20 | Montreal Braves |
| 2 | Mervin | Webb | lead | 5 | 1.0 | M | 11 | Stone Timberwolves |
| 3 | Issa | Sharma | lead | 4 | 1.0 | M | 15 | Stone Timberwolves |
| 4 | Daylen | Larsen | lead | 4 | 1.0 | M | 17 | Montreal Braves |
| 5 | Craig | McCarthy | lead | 3 | 1.0 | M | 10 | Montreal Braves |
best_for_position(team_junior_m, 'vice')
| first_name | last_name | position | played | success_rate | gender | age | team_name | |
|---|---|---|---|---|---|---|---|---|
| 1 | Daylen | Larsen | vice | 7 | 1.0 | M | 17 | Montreal Braves |
| 2 | Olivier | Donovan | vice | 6 | 1.0 | M | 17 | Stone Timberwolves |
| 3 | Frederik | Adam | vice | 4 | 1.0 | M | 11 | Super Salsa |
| 4 | Mervin | Webb | vice | 4 | 1.0 | M | 11 | Stone Timberwolves |
| 5 | Timur | Labelle | vice | 3 | 1.0 | M | 12 | Broom Hawks |
best_for_position(team_junior_m, 'second')
| first_name | last_name | position | played | success_rate | gender | age | team_name | |
|---|---|---|---|---|---|---|---|---|
| 1 | Tal | Ho | second | 7 | 1.0 | M | 13 | Stone Timberwolves |
| 2 | Craig | McCarthy | second | 5 | 1.0 | M | 10 | Montreal Braves |
| 3 | Boy | Edwards | second | 4 | 1.0 | M | 13 | Broom Hawks |
| 4 | Carl | Perron | second | 4 | 1.0 | M | 10 | Montreal Braves |
| 5 | Khaled | David | second | 4 | 1.0 | M | 8 | Super Salsa |
best_for_position(team_junior_m, 'skip')
| first_name | last_name | position | played | success_rate | gender | age | team_name | |
|---|---|---|---|---|---|---|---|---|
| 1 | Tal | Ho | skip | 6 | 1.0 | M | 13 | Stone Timberwolves |
| 2 | Carl | Perron | skip | 5 | 1.0 | M | 10 | Montreal Braves |
| 3 | Jahaan | Turgeon | skip | 5 | 1.0 | M | 9 | Toronto Olympics |
| 4 | Israel | Chevalier | skip | 4 | 1.0 | M | 20 | Montreal Braves |
| 5 | Craig | McCarthy | skip | 4 | 1.0 | M | 10 | Montreal Braves |
Ponownie najlepsi zawodnicy są z tylko kilku drużyn, tutaj: Montreal Braves, Stone Timberwolves, Super Salsa, Broom Hawks i Toronto Olympics. Co ciekawe mamy zawodnika (Tal Ho) który jest jednoznacznie najlepszy w dwóch kategoriach.
Z powyższych odczytujemy nasze możliwe opcje:
Najpierw rozwiązujemy kwestię na jaką pozycję trafi Tal Ho, lepsza sytuacja będzie gdzy zajmie on pozycję 'second' a wtedy zamiast niego Carl Perron zostanie 'skip'. Jest tak ponieważ widzimy mniejszą różnicę między umiejętnościami Tal Ho i Carl Perron niż między Tal Ho i Craig McCarthy. Jako 'lead' wybieramy bezsprzecznie Israel Chevalier, który jest naszym najlepszym graczem wśród juniorów!
Reprezentacja męska juniorów prezentuje się następjąco:
query_junior_w = '''
SELECT first_name, last_name, positions.position, SUM(team_score > opponent_score), COUNT(team_score > opponent_score), gender, birthdate, team_name
FROM positions
LEFT JOIN people USING (person_id)
LEFT JOIN gender USING (first_name)
LEFT JOIN personal_info USING (person_id)
LEFT JOIN matches USING (team_name, date)
LEFT JOIN teams USING (team_name)
WHERE (team_score IS NOT NULL) AND (age_category = 'junior') AND (gender = 'F')
GROUP BY person_id, positions.position
'''
cursor.execute(query_junior_w)
team_junior_w = cursor.fetchall()
team_junior_w = pd.DataFrame(team_junior_w, columns=['first_name', 'last_name', 'position', 'won', 'played', 'gender', 'birthdate', 'team_name'])
best_for_position(team_junior_w, 'lead')
| first_name | last_name | position | played | success_rate | gender | age | team_name | |
|---|---|---|---|---|---|---|---|---|
| 1 | Elysse | Prevost | lead | 5 | 1.0 | F | 15 | Cold Islanders |
| 2 | Adaline | Parsons | lead | 4 | 1.0 | F | 11 | Cold Islanders |
| 3 | Female | Hewitt | lead | 3 | 1.0 | F | 14 | Ottawa Greys |
| 4 | Chastity | Tessier | lead | 3 | 1.0 | F | 9 | Toronto Olympics |
| 5 | Rania | Faucher | lead | 2 | 1.0 | F | 17 | Calgary Metros |
best_for_position(team_junior_w, 'vice')
| first_name | last_name | position | played | success_rate | gender | age | team_name | |
|---|---|---|---|---|---|---|---|---|
| 1 | Liliane | Freeman | vice | 4 | 1.0 | F | 11 | Montreal Lasers |
| 2 | Elysse | Prevost | vice | 4 | 1.0 | F | 15 | Cold Islanders |
| 3 | Hester | Newton | vice | 4 | 1.0 | F | 18 | Montreal Lasers |
| 4 | Mackayla | Little | vice | 3 | 1.0 | F | 12 | Toronto Olympics |
| 5 | Petra | Reimer | vice | 3 | 1.0 | F | 12 | Cold Islanders |
best_for_position(team_junior_w, 'second')
| first_name | last_name | position | played | success_rate | gender | age | team_name | |
|---|---|---|---|---|---|---|---|---|
| 1 | Ksenia | Godin | second | 6 | 1.0 | F | 10 | Cold Islanders |
| 2 | Braelynn | Beaton | second | 3 | 1.0 | F | 19 | Stone Timberwolves |
| 3 | Simra | Nielsen | second | 3 | 1.0 | F | 11 | Ice Dodgers |
| 4 | Niki | Croteau | second | 3 | 1.0 | F | 12 | Cold Islanders |
| 5 | Mykayla | Champagne | second | 3 | 1.0 | F | 20 | Super Atlantics |
best_for_position(team_junior_w, 'skip')
| first_name | last_name | position | played | success_rate | gender | age | team_name | |
|---|---|---|---|---|---|---|---|---|
| 1 | Adaline | Parsons | skip | 5 | 1.0 | F | 11 | Cold Islanders |
| 2 | Leita | Lam | skip | 3 | 1.0 | F | 13 | Montreal Lasers |
| 3 | Delma | Davis | skip | 3 | 1.0 | F | 16 | Montreal Lasers |
| 4 | Rachel | ONeill | skip | 2 | 1.0 | F | 10 | Montreal Lasers |
| 5 | Rania | Faucher | skip | 2 | 1.0 | F | 17 | Calgary Metros |
Na koniec szukamy jeszcze reprezentacji kobiet dla juniorów. Jak zwykle mamy pule kilku najlepszych drużyn z których pochodzą nasze zawodniczki, są to: Cold Islanders, Ottawa Greys, Toronto Olympics, Calgary Metros, Montreal Lasers, Stone Timberwolves, Ice Dodger oraz Super Atlantics. Pula tutaj znacznie się nam powiększyła, co znaczy, że drużyny żeńskie są bardziej zróżnicowane.
W tej kategorii mamy następujące kandydatki:
Jedyna sporna pozycja, to 'vice' z której odpada nam Elysse Prevost, będąca naszym 'lead'. Liliane Freeman i Hester Newton nie pojawiają się w top $40$ zawodników ani żadna nie jest z drużyny pozostałych zawodniczek, więc zupełnie zmieniamy taktykę i wybieramy Petra Reimer. Znajduje się ona w Cold Islanders, jest $7$ najlepszą zawodniczką wśród juniorów, a różnica w jej umiejętnościach i wytypowanych dziewczyn jest niewielka.
Nasza reprezentacja żeńska juniorów pochodzi cała z drużyny Cold Islanders i składa się z:
Początkowo chcemy na podstawie wydatków i zarobków tylko w kwietniu 2022, aby nasz bilans wyniósł 0 albo był dodatni.
Zacznijmy od sprawdzenia wydatków, których nie udało nam się pokryć w kwietniu 2022 z opłat za członkostwo.
query5 = "SELECT SUM(financial_flow) FROM finances WHERE date LIKE '2022-04-%'"
cursor.execute(query5)
results5 = cursor.fetchone()
debt = results5[0]
print("Nasz bilans w kwietniu 2022 wyniósł %.2f$." % debt)
Nasz bilans w kwietniu 2022 wyniósł -460665.30$.
print("Potrzebowalibyśmy {} nowych juniorów.".format(int(np.ceil(np.abs(debt/20)))))
Potrzebowalibyśmy 23034 nowych juniorów.
print("Potrzebowalibyśmy {} nowych dorosłych.".format(int(np.ceil(np.abs(debt/55)))))
Potrzebowalibyśmy 8376 nowych dorosłych.
print("Potrzebowalibyśmy {} nowych graczy juniorów i {} nowych graczy dorosłych. (Przy założeniu, że każda grupa graczy pokryłaby taką samą część nadmiarowych wydatków.)".format(int(np.ceil(np.abs(debt/2/20))), int(np.ceil(np.abs(debt/2/55)))))
Potrzebowalibyśmy 11517 nowych graczy juniorów i 4188 nowych graczy dorosłych. (Przy założeniu, że każda grupa graczy pokryłaby taką samą część nadmiarowych wydatków.)
i = 1
while True:
if 20*i + 55* i > np.abs(debt):
break
i += 1
print("Potrzebowalibyśmy {} nowych graczy juniorów i {} nowych graczy dorosłych. (Przy założeniu, że dołączyłoby tyle samo nowych zawodników z obu grup wiekowych.)".format(i, i))
Potrzebowalibyśmy 6143 nowych graczy juniorów i 6143 nowych graczy dorosłych. (Przy założeniu, że dołączyłoby tyle samo nowych zawodników z obu grup wiekowych.)
A ilu właściwie mamy graczy w tym momencie?
query6 = "SELECT COUNT(*) FROM personal_info WHERE position IS NULL"
cursor.execute(query6)
results6 = cursor.fetchone()
results6[0]
370
Niestety patrząc na to, że aktualnie mamy zaledwie 370 zawodników, ciężko byłoby nam zdobyć parę czy parędziesiąt tysięcy nowych graczy. Musimy więc znaleźć inne źródło zarobku. Zatem...
Jak wiemy, za wygrane mecze czasami możemy otrzymać nagrody pieniężne, których dotąd nie roważałyśmy. Przyjmijmy więc, że otrzymaliśmy nagrodę w każdym meczu, który wygraliśmy w kwietniu 2022.
Ile meczy udało nam się wygrać w kwietniu 2022?
query7 = "SELECT COUNT(*) FROM matches WHERE (date LIKE '2022-04-%') AND (team_score > opponent_score)"
cursor.execute(query7)
results7 = cursor.fetchone()
won_matches = results7[0]
print("W kwietniu 2022 udało nam się wygrać {} meczy.".format(won_matches))
W kwietniu 2022 udało nam się wygrać 27 meczy.
print("Potrzebowalibyśmy za każdy wygrany mecz otrzymać {}$.".format(np.ceil(np.abs(debt/won_matches)*100)/100))
Potrzebowalibyśmy za każdy wygrany mecz otrzymać 17061.68$.
Oczywiście widzimy, że mamy raczej małe szanse, aby za każdą wygraną otrzymać kwotę 17 tysięcy dolarów. Pora zatem poszukać sponsorów.
Znalazłyśmy dane, które mówiły, że sponsoring drużyny sportowej to średnio od $100\$$ do $3000\$$. Rozważymy więc sponsorów, którzy każdej z naszych drużyn przekazują miesięcznie taką samą kwotę.
Załóżmy najpierw, że każdy ze sponsorów miesięcznie przekazywałby nam kwotę $100\$$ na drużynę.
print("Potrzebowalibyśmy {} takich sponsorów.".format(int(np.ceil(np.abs(debt/(100*43))))))
Potrzebowalibyśmy 108 takich sponsorów.
Ale jeśli każdy ze sponsorów miesięcznie przekazywałby nam kwotę 500$ na drużynę...
print("Potrzebowalibyśmy {} takich sponsorów.".format(int(np.ceil(np.abs(debt/(500*43))))))
Potrzebowalibyśmy 22 takich sponsorów.
A co gdybyśmy mieli bardziej hojnych sponsorów, którzy przekazywaliby miesięcznie 3000$ każdej drużynie?
print("Potrzebowalibyśmy już tylko {} takich sponsorów.".format(int(np.ceil(np.abs(debt/(3000*43))))))
Potrzebowalibyśmy już tylko 4 takich sponsorów.
Dość logiczne jest, że nowych zawodników pojawi się tylko ograniczona liczba, dlatego znacząco nie zwiększą oni naszych zysków. Ponadto, aby zająć się kolejnymi graczami, potrzebowalibyśmy więcej pracowników, co ponownie zwiększyłoby nasze wydatki.
Zdecydowanie najlepszym rozwiązaniem byłoby znalezienie sponsorów. Oczywiście ciężko pozyskać takich, którzy płaciliby kilka tysięcy dolarów miesięcznie każdej z naszych drużyn, jednak jacykolwiek sponsorzy pozytywnie wpłynęliby na bilans naszego konta.
Oczywiście powinniśmy też zacząć brać udział w meczach, w których za zwycięstwo moglibyśmy otrzymać nagrody pieniężne, a dodatkowo wygrywając - przekonać do sponsorowania nas.
query8 = '''SELECT city, position, COUNT(*)
FROM people
LEFT JOIN gender
USING(first_name)
LEFT JOIN address
USING(person_id)
LEFT JOIN address_book
USING(address_id)
LEFT JOIN personal_info
USING(person_id)
WHERE position IS NOT NULL
AND retire_date IS NULL
GROUP BY city, position'''
cursor.execute(query8)
results8 = cursor.fetchall()
employees = pd.DataFrame(results8, columns=["city", "position", "amount"])
def make_position(df, col:int):
fig.add_trace(go.Pie(values=df['amount'], labels=df['position']), 1, col)
fig.update_traces(textinfo="value")
fig = make_subplots(rows=1, cols=5, specs=[[{'type':'domain'}, {'type':'domain'}, {'type':'domain'}, {'type':'domain'}, {'type':'domain'}]], subplot_titles=employees["city"].unique())
i = 1
for city in employees["city"].unique():
make_position(employees[employees["city"]==city], i)
i += 1
fig.update_layout(title_text="Podział wszystkich aktywnych pracowników w poszczególnych placówkach ze względu na stanowisko", title_x=0.5)
fig.show()
Widzimy, że największe grupy pracowników stanowią managerowie, sprzątaczki oraz trenerzy. Managerów mamy dokładnie tylu, ile drużyn w danej placówce. Jest to dość spora ilość, szczególnie, że w niektórych placówkach jest ich więcej niż sprzątaczek. W każdej placówce mamy dokładnie jednego dyrektora. Ilość księgowych, psychologów oraz lekarzy w każdej z placówek waha się między 1 a 3. Najwięcej trenerów znajduje się w Calgary, skąd co ciekawe pochodzi najlepsza drużyna Calgary Rockets.
query9 = '''SELECT city, gender, COUNT(*)
FROM people
LEFT JOIN gender
USING(first_name)
LEFT JOIN address
USING(person_id)
LEFT JOIN address_book
USING(address_id)
LEFT JOIN personal_info
USING(person_id)
WHERE position IS NULL
AND retire_date IS NULL
GROUP BY city, gender'''
cursor.execute(query9)
results9 = cursor.fetchall()
players_gender = pd.DataFrame(results9, columns=["city", "gender","amount"])
players_gender = players_gender.replace(['M'],'male')
players_gender = players_gender.replace(['F'],'female')
def make_gender(df, col:int):
fig.add_trace(go.Pie(values=df['amount'], labels=df['gender']), 1, col)
fig.update_traces(textinfo="value")
fig = make_subplots(rows=1, cols=5, specs=[[{'type':'domain'}, {'type':'domain'}, {'type':'domain'}, {'type':'domain'}, {'type':'domain'}]], subplot_titles=players_gender["city"].unique())
i = 1
for city in players_gender["city"].unique():
make_gender(players_gender[players_gender["city"]==city], i)
i += 1
fig.update_layout(title_text="Podział wszystkich aktywnych graczy w poszczególnych placówkach ze względu na płeć", title_x=0.5)
fig.show()
W Ottawie mamy najwięcej kobiet i stanowią one ponad 60% wszystkich aktywnych graczy w tej placówce. W pozostałych placówkach przeważają natomiast mężczyźni. Przewaga mężczyzn była już wcześniej widoczna przy wykresie ilości aktywnych zawodników. Ilość mężczyzn i kobiet jest mocno zróżnicowana i zależy od kategorii zespołów w danej placówce.
query10 = '''SELECT city, SUM(retire_date IS NULL), SUM(retire_date IS NOT NULL)
FROM people
LEFT JOIN personal_info
USING(person_id)
LEFT JOIN address
USING(person_id)
LEFT JOIN address_book
USING(address_id)
GROUP BY city
'''
cursor.execute(query10)
results10 = cursor.fetchall()
players_activity = pd.DataFrame(results10, columns=["city", "active", "retired"])
players_activity = players_activity.astype({"active": int, "retired":int})
def make_position(df, col:int):
fig.add_trace(go.Pie(values=[df[['active']].iloc[0,0],df[['retired']].iloc[0,0]], labels=["active", "retired"]), 1, col)
fig.update_traces(textinfo="value")
fig = make_subplots(rows=1, cols=5, specs=[[{'type':'domain'}, {'type':'domain'}, {'type':'domain'}, {'type':'domain'}, {'type':'domain'}]], subplot_titles=players_activity["city"].unique())
i = 1
for city in players_activity["city"].unique():
make_position(players_activity[players_activity["city"]==city], i)
i += 1
fig.update_layout(title_text="Podział wszystkich graczy w poszczególnych placówkach ze względu na bycie aktywnym", title_x=0.5)
fig.show()
Widzimy, że w każdej z placówek około 25% zawodników odeszło, a około 75% to nadal aktywni gracze. Ilościowo najwięcej graczy odeszło w Montrealu, natomiast procentowo - w Toronto. Wszędzie ilość zawodników, którzy odeszli waha się w przedziale od 25 do 35.